#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
天翼云WebDAV项目全局配置文件
统一管理数据库、端口、WebDAV路径等配置
"""

import os
from typing import Dict, Any, Optional, Union
from pathlib import Path
from dotenv import load_dotenv

class ConfigValidationError(Exception):
    """配置验证错误"""
    pass

class GlobalConfig:
    """全局配置管理类"""
    
    def __init__(self):
        """初始化配置"""
        self._env_loaded = self._load_env_file()
        self._config = self._load_config()
        self._validate_config()
    
    def _load_env_file(self) -> bool:
        """加载.env文件，返回是否成功加载"""
        env_path = Path(__file__).parent.parent.parent / '.env'
        if env_path.exists():
            load_dotenv(env_path)
            print(f"✅ 已加载环境配置文件: {env_path}")
            return True
        else:
            print(f"⚠️ 环境配置文件不存在: {env_path}")
            print("📝 将使用默认配置，建议复制 .env.example 为 .env 并修改配置")
            return False
    
    def _get_env_value(self, key: str, default_value, value_type=str):
        """安全获取环境变量值，支持类型转换"""
        try:
            value = os.getenv(key)
            if value is None:
                return default_value
            
            if value_type == bool:
                return value.lower() in ('true', '1', 'yes', 'on')
            elif value_type == int:
                return int(value)
            elif value_type == float:
                return float(value)
            else:
                return value
        except (ValueError, TypeError):
            print(f"⚠️ 环境变量 {key} 值格式错误，使用默认值: {default_value}")
            return default_value

    def _validate_config(self):
        """验证配置的完整性和合理性"""
        errors = []
        
        # 验证WebDAV配置
        webdav_config = self._config['webdav']
        
        # 验证端口号
        port = webdav_config.get('port', 0)
        if not isinstance(port, int) or port < 1 or port > 65535:
            errors.append(f"WebDAV端口号无效: {port}")
        
        # 验证主机地址
        host = webdav_config.get('host', '')
        if not host or not isinstance(host, str):
            errors.append(f"WebDAV主机地址无效: {host}")
        
        # 验证上传大小限制
        max_upload_size = webdav_config.get('max_upload_size', 0)
        if not isinstance(max_upload_size, int) or max_upload_size <= 0:
            errors.append(f"最大上传大小无效: {max_upload_size}")
        
        # 验证数据库配置
        db_config = self._config['database']
        
        # 验证数据库端口
        db_port = db_config.get('port', 0)
        if not isinstance(db_port, int) or db_port < 1 or db_port > 65535:
            errors.append(f"数据库端口号无效: {db_port}")
        
        # 验证必要的数据库参数
        required_db_fields = ['host', 'database', 'username', 'password']
        for field in required_db_fields:
            if not db_config.get(field):
                errors.append(f"数据库配置缺少必要字段: {field}")
        
        # 验证应用配置
        app_config = self._config['app']
        
        # 验证日志级别
        valid_log_levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
        log_level = app_config.get('log_level', '').upper()
        if log_level not in valid_log_levels:
            errors.append(f"日志级别无效: {log_level}，有效值: {valid_log_levels}")
        
        if errors:
            error_msg = "配置验证失败:\n" + "\n".join(f"  - {error}" for error in errors)
            raise ConfigValidationError(error_msg)
    
    def _load_config(self) -> Dict[str, Any]:
        """加载配置，优先从.env文件读取，否则使用默认值"""
        return {
            # 数据库配置
            'database': {
                'host': self._get_env_value('DB_HOST', '121.37.130.94'),
                'port': self._get_env_value('DB_PORT', 33306, int),
                'database': self._get_env_value('DB_NAME', 'tianyi_webdav'),
                'username': self._get_env_value('DB_USER', 'root'),
                'password': self._get_env_value('DB_PASSWORD', 'mysql_hfK6FQ'),
                'charset': self._get_env_value('DB_CHARSET', 'utf8mb4'),
                'pool_size': self._get_env_value('DB_POOL_SIZE', 10, int),
                'max_overflow': self._get_env_value('DB_MAX_OVERFLOW', 20, int),
                'pool_timeout': self._get_env_value('DB_POOL_TIMEOUT', 30, int),
                'pool_recycle': self._get_env_value('DB_POOL_RECYCLE', 3600, int)
            },
            
            # WebDAV服务配置
            'webdav': {
                'host': self._get_env_value('WEBDAV_HOST', '0.0.0.0'),
                'port': self._get_env_value('WEBDAV_PORT', 8080, int),
                'base_path': self._get_env_value('WEBDAV_BASE_PATH', ''),
                'auth_required': self._get_env_value('WEBDAV_AUTH_REQUIRED', True, bool),
                'debug': self._get_env_value('WEBDAV_DEBUG', False, bool),
                'max_upload_size': self._get_env_value('WEBDAV_MAX_UPLOAD_SIZE', 1024 * 1024 * 1024, int),
                'chunk_size': self._get_env_value('WEBDAV_CHUNK_SIZE', 8192, int),
                'timeout': self._get_env_value('WEBDAV_TIMEOUT', 300, int),
                'enable_download_redirect': self._get_env_value('WEBDAV_ENABLE_DOWNLOAD_REDIRECT', True, bool),
                'download_url_cache_timeout': self._get_env_value('WEBDAV_DOWNLOAD_URL_CACHE_TIMEOUT', 3600, int),
                'rapid_upload_base_path': self._get_env_value('WEBDAV_RAPID_UPLOAD_BASE_PATH', '/rapid_upload'),
                'cors_enabled': self._get_env_value('WEBDAV_CORS_ENABLED', True, bool),
                'dir_browser_enabled': self._get_env_value('WEBDAV_DIR_BROWSER_ENABLED', True, bool),
                'lock_storage_enabled': self._get_env_value('WEBDAV_LOCK_STORAGE_ENABLED', True, bool),
                'property_manager_enabled': self._get_env_value('WEBDAV_PROPERTY_MANAGER_ENABLED', True, bool)
            },
            
            # 应用配置
            'app': {
                'name': self._get_env_value('APP_NAME', '天翼云WebDAV服务'),
                'version': self._get_env_value('APP_VERSION', '2.0.0'),
                'debug': self._get_env_value('APP_DEBUG', False, bool),
                'max_content_length': self._get_env_value('APP_MAX_CONTENT_LENGTH', 1024 * 1024 * 1024, int),
                'log_level': self._get_env_value('LOG_LEVEL', 'INFO'),
                'log_file': self._get_env_value('LOG_FILE', 'logs/webdav.log'),
                'max_log_size': self._get_env_value('LOG_MAX_SIZE', 10 * 1024 * 1024, int),
                'log_backup_count': self._get_env_value('LOG_BACKUP_COUNT', 5, int),
                'secret_key': self._get_env_value('APP_SECRET_KEY', 'tianyi-webdav-secret-key-2024'),
                'timezone': self._get_env_value('APP_TIMEZONE', 'Asia/Shanghai')
            },
            
            # 云盘配置
            'cloud': {
                'tianyi': {
                    'enabled': self._get_env_value('CLOUD_TIANYI_ENABLED', True, bool),
                    'default_account': self._get_env_value('CLOUD_TIANYI_DEFAULT_ACCOUNT', ''),
                    'default_password': self._get_env_value('CLOUD_TIANYI_DEFAULT_PASSWORD', ''),
                    'display_name': self._get_env_value('CLOUD_TIANYI_DISPLAY_NAME', '默认天翼云账号'),
                    'timeout': self._get_env_value('CLOUD_TIANYI_TIMEOUT', 30, int),
                    'retry_count': self._get_env_value('CLOUD_TIANYI_RETRY_COUNT', 3, int),
                    'cache_expire': self._get_env_value('CLOUD_TIANYI_CACHE_EXPIRE', 3600, int),
                    'max_concurrent_downloads': self._get_env_value('CLOUD_TIANYI_MAX_CONCURRENT_DOWNLOADS', 5, int),
                    'download_chunk_size': self._get_env_value('CLOUD_TIANYI_DOWNLOAD_CHUNK_SIZE', 1024 * 1024, int)
                }
            },
            
            # 扩展功能配置
            'extensions': {
                'import': {
                    'batch_size': self._get_env_value('EXT_IMPORT_BATCH_SIZE', 100, int),
                    'max_workers': self._get_env_value('EXT_IMPORT_MAX_WORKERS', 4, int),
                    'timeout': self._get_env_value('EXT_IMPORT_TIMEOUT', 300, int)
                },
                'cache': {
                    'enabled': self._get_env_value('EXT_CACHE_ENABLED', True, bool),
                    'expire_time': self._get_env_value('EXT_CACHE_EXPIRE_TIME', 3600, int),
                    'max_size': self._get_env_value('EXT_CACHE_MAX_SIZE', 1000, int)
                },
                'performance': {
                    'monitor_enabled': self._get_env_value('EXT_PERFORMANCE_MONITOR_ENABLED', True, bool),
                    'metrics_retention_days': self._get_env_value('EXT_PERFORMANCE_METRICS_RETENTION_DAYS', 7, int),
                    'slow_request_threshold': self._get_env_value('EXT_PERFORMANCE_SLOW_REQUEST_THRESHOLD', 5.0, float)
                }
            }
        }
    
    def get_config_status(self) -> Dict[str, Any]:
        """获取配置状态信息"""
        env_path = Path(__file__).parent.parent.parent / '.env'
        return {
            'env_file_exists': env_path.exists(),
            'env_file_path': str(env_path),
            'env_loaded': self._env_loaded,
            'config_valid': True,  # 如果到这里说明配置验证通过
            'webdav_host': self._config['webdav']['host'],
            'webdav_port': self._config['webdav']['port'],
            'database_host': self._config['database']['host'],
            'database_port': self._config['database']['port']
        }
    
    def print_config_status(self):
        """打印配置状态"""
        status = self.get_config_status()
        print("\n=== 配置状态 ===")
        print(f"环境文件存在: {'是' if status['env_file_exists'] else '否'}")
        print(f"环境文件路径: {status['env_file_path']}")
        print(f"环境变量加载: {'成功' if status['env_loaded'] else '失败'}")
        print(f"配置验证: {'通过' if status['config_valid'] else '失败'}")
        print(f"WebDAV服务: {status['webdav_host']}:{status['webdav_port']}")
        print(f"数据库服务: {status['database_host']}:{status['database_port']}")
        print("=" * 30)
    
    def validate_webdav_config(self) -> Dict[str, Any]:
        """专门验证WebDAV配置"""
        webdav_config = self._config['webdav']
        validation_result = {
            'valid': True,
            'errors': [],
            'warnings': []
        }
        
        # 检查端口可用性
        import socket
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.bind((webdav_config['host'], webdav_config['port']))
        except OSError as e:
            if e.errno == 98:  # Address already in use
                validation_result['errors'].append(f"端口 {webdav_config['port']} 已被占用")
                validation_result['valid'] = False
            elif e.errno == 99:  # Cannot assign requested address
                validation_result['errors'].append(f"无法绑定到地址 {webdav_config['host']}")
                validation_result['valid'] = False
        
        # 检查上传大小限制
        max_upload_mb = webdav_config['max_upload_size'] / (1024 * 1024)
        if max_upload_mb > 2048:  # 大于2GB
            validation_result['warnings'].append(f"最大上传大小较大: {max_upload_mb:.0f}MB")
        
        # 检查基础路径格式
        base_path = webdav_config['base_path']
        if base_path and not base_path.startswith('/'):
            validation_result['warnings'].append(f"基础路径建议以'/'开头: {base_path}")
        
        return validation_result

    def get(self, key: str, default=None):
        """获取配置值，支持点号分隔的嵌套键"""
        keys = key.split('.')
        value = self._config
        
        try:
            for k in keys:
                value = value[k]
            return value
        except (KeyError, TypeError):
            return default
    
    def set(self, key: str, value):
        """设置配置值，支持点号分隔的嵌套键"""
        keys = key.split('.')
        config = self._config
        
        # 导航到最后一级的父级
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
        
        # 设置值
        config[keys[-1]] = value
    
    def get_database_config(self) -> Dict[str, Any]:
        """获取数据库配置"""
        return self._config['database']
    
    def get_database_url(self) -> str:
        """获取数据库连接URL"""
        db_config = self._config['database']
        return f"mysql+pymysql://{db_config['username']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}?charset={db_config['charset']}"
    
    def get_webdav_config(self) -> Dict[str, Any]:
        """获取WebDAV配置"""
        return self._config['webdav']
    
    def get_app_config(self) -> Dict[str, Any]:
        """获取应用配置"""
        return self._config['app']
    
    def get_cloud_config(self, provider: str = 'tianyi') -> Dict[str, Any]:
        """获取云盘配置"""
        return self._config['cloud'].get(provider, {})
    
    def get_extension_config(self, extension: str = None) -> Dict[str, Any]:
        """获取扩展配置"""
        if extension:
            return self._config['extensions'].get(extension, {})
        return self._config['extensions']
    
    def is_debug(self) -> bool:
        """是否为调试模式"""
        return self._config['app']['debug'] or self._config['webdav']['debug']
    
    def get_log_config(self) -> Dict[str, Any]:
        """获取日志配置"""
        app_config = self._config['app']
        return {
            'level': app_config['log_level'],
            'file': app_config['log_file'],
            'max_size': app_config['max_log_size'],
            'backup_count': app_config['log_backup_count']
        }

# 全局配置实例
try:
    config = GlobalConfig()
except ConfigValidationError as e:
    print(f"❌ 配置验证失败: {e}")
    print("请检查配置文件并修正错误后重新启动")
    raise

# 便捷函数
def get_config(key: str, default=None):
    """获取配置值"""
    return config.get(key, default)

def set_config(key: str, value):
    """设置配置值"""
    return config.set(key, value)

def get_database_config():
    """获取数据库配置"""
    return config.get_database_config()

def get_database_url():
    """获取数据库连接URL"""
    return config.get_database_url()

def get_webdav_config():
    """获取WebDAV配置"""
    return config.get_webdav_config()

def get_app_config():
    """获取应用配置"""
    return config.get_app_config()

def get_cloud_config(provider: str = 'tianyi'):
    """获取云盘配置"""
    return config.get_cloud_config(provider)

def get_extension_config(extension: str = None):
    """获取扩展配置"""
    return config.get_extension_config(extension)

def is_debug():
    """是否为调试模式"""
    return config.is_debug()

def get_log_config():
    """获取日志配置"""
    return config.get_log_config()

def get_db_config():
    """获取数据库配置（兼容性函数）"""
    return config.get_database_config()

def validate_webdav_config():
    """验证WebDAV配置"""
    return config.validate_webdav_config()